library(ggplot2)
package ‘ggplot2’ was built under R version 3.6.2
library(CodeClanData)

Attaching package: ‘CodeClanData’

The following object is masked from ‘package:datasets’:

    volcano
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ───────────────────────────────────────────────────── tidyverse 1.3.0 ──
✓ tibble  3.0.3     ✓ dplyr   1.0.0
✓ tidyr   1.1.0     ✓ stringr 1.4.0
✓ readr   1.3.1     ✓ forcats 0.5.0
✓ purrr   0.3.4     
package ‘tibble’ was built under R version 3.6.2package ‘tidyr’ was built under R version 3.6.2package ‘purrr’ was built under R version 3.6.2package ‘dplyr’ was built under R version 3.6.2── Conflicts ──────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(ggthemes)
library(viridis)
Loading required package: viridisLite

COMPARISON

Create a suitable plot for the following three datasets:


late_deliveries

Late Deliveries

ggplot(late_deliveries) +
 aes(x = date, y = late_deliveries, fill = late_deliveries, bins = 20) +
  geom_col(position = "dodge") +
  scale_fill_distiller(palette = "Pastel2") +
  theme_bw() + 
  labs(
    x = "Date",
    y = "late deliveries",
    title = "Late Deliveries"
  ) +  
  theme(title = element_text(size = 16, face = "italic", colour = "Blue"))

solution 2


ggplot(late_deliveries) +
  aes(x = date, y = late_deliveries) +
  geom_line() + 
  geom_point() + 
  labs(x = "year", y = "number of late deliveries") + 
  theme_minimal()

Recovery time


recovery_times
ggplot(recovery_times) +
  aes(x = recovery, y = prognosis, fill = treatment_group) + 
  geom_col(position = "dodge") +
  scale_fill_hue(h = c(120,300), c = 40, l = 45) +
  theme_classic(11) +
  labs(
    x = "Recovery",
    y = "Prognosis",
    title = "Recovery Times"
  ) +
  theme(
    title = element_text(size = 15, face = "bold", colour = "blue"),
    panel.background = element_rect(fill = "Pink"), 
    panel.grid = element_blank(),
    plot.title = element_text(size = 15, face = "bold", colour = "blue")
  )

NA
NA

solution 2

ggplot(recovery_times) +
  aes(x = treatment_group, y = recovery, fill = prognosis) +
  geom_col(position = "dodge") + 
  labs(x = "\n Treatment Group", y = "Recovery time (months) \n") + 
    scale_fill_colorblind()

NA
NA

Fitness Level

fitness_levels

ggplot(fitness_levels) + 
  aes(x = age, y = fitness_score, colour = group) +
  geom_line() +
  theme_light() + 
  facet_wrap(~ group, ncol = 10, scales = "free") +
  scale_color_gradient2_tableau()

NA
NA

Solution 2

ggplot(fitness_levels) +
  aes(x = age, y = fitness_score, group = child, color = child) +
  geom_line() +
  geom_point() +
  facet_wrap(~ group, ncol = 5) + 
  labs(y = "fitness score \n", x = "\n age (years)", title = "Individual child fitness score by Group") + 
  scale_colour_hue(guide = guide_legend(nrow = 10, byrow = TRUE))

CONNECTION

Blood Pressure

ggplot(blood_pressure) +
  aes(x = systolic_blood_pressure_mm_hg, y = daily_saturated_fat_intake_mg, colour = daily_saturated_fat_intake_mg) +
  geom_point() +
  scale_colour_gradient2(low = "blue", high = "red", mid = "white", midpoint = 15) +
  labs(
    x = "Sys Blood Pre",
    y = "Daily fat intake (mg)",
    title = "Blood Pressue",
    subtitle = "fat Intake (mg)"
  ) + 
  theme_light()

Solution 2

ggplot(blood_pressure) +
  aes(
    x = daily_saturated_fat_intake_mg,
    y = systolic_blood_pressure_mm_hg
  ) +
  geom_point() + 
  labs(x = "daily fat intake (mg)", y = "systolic blood pressure (mmHg)")

Car use

car_use
ggplot(car_use) +
  aes(x = city, y = population, colour = car_use_percent) +
  geom_point() +
  scale_color_distiller(palette = "PuOr") +
  theme_dark() +
  labs(
    title = "Car Use", 
    subtitle = "Car use"
  )

NA
NA
NA

solution 2

ggplot(car_use) +
  aes(
    x = car_use_percent,
    y = air_so2_concentration_ppm,
    size = population
  ) +
  geom_point(alpha = 0.5) + 
  labs(x = "car use (%)", y = "air CO2 concentration (ppm)")

DISTRIBUTION

D20 Outcome

ggplot(d20_outcomes) +
  aes(x = outcome) +
  geom_histogram(bins = 20, col = "white") 

solution 2

ggplot(d20_outcomes) +
  aes(x = outcome) +
  geom_density()

COMPOSITION

Pension Surplus

ggplot(pension_surplus) +
  aes(x = item, y = balance, fill = balance > 0) +
  geom_col() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) + 
  coord_flip() 

Pension Liabilities

ggplot(pension_liabilities) +
  aes(x = year, y = liability_millions, fill = liability_type) +
  geom_col() + 
  scale_fill_colorblind()

Homework part 1

library(ggplot2)
library(CodeClanData)
library(dplyr)
  1. Take the data in the dataset qb_revenue_breakdown and make a stacked bar chart showing the sources of revenue across the two years in the dataset.
ggplot(qb_revenue_breakdown) +
  aes(x = Year, y = Revenue, fill = Product) +
  geom_col()

  1. Make a line chart showing monthly sales of the “flagship product” - the KwikBit Unit1 - over the last year. This data is inside qb_monthly_sales, but you will need to use subset.

kwikbit_sales <- subset(qb_monthly_sales, Cashflow == "Kwikbit Unit 1 Sales")

ggplot(kwikbit_sales) +
  aes(x = Date, y = Amount) +
  geom_line() 

  1. Make a line chart showing monthly revenue and costs over the last year. This data is also in qb_monthly_sales.
revenue_and_costs <- subset(qb_monthly_sales, Cashflow != "Kwikbit Unit 1 Sales")

ggplot(revenue_and_costs) +
  aes(x = Date, y = Amount, colour = Cashflow) +
  geom_line()

  1. Show annual sales of personal fitness trackers over the last 5 years broken down by company as a ribbon plot (use geom_area). This data is in qb_competitors.
ggplot(qb_competitors) +
  aes(x = Year, y = Revenue, fill = Company) +
  geom_area() 

  1. Now show the sales from the 5 competitors as a line graph. Include an extra layer that shows the data points used to make the lines.
ggplot(qb_competitors) +
  aes(x = Year, y = Revenue, colour = Company) +
  geom_line() +
  geom_point()

  1. Now the company wants to compare the number of steps that their device counts vs. their competitors. Make a line graph of the number of steps throughout time, and use faceting to compare between individuals and people. Data is in qb_device_data.
qb_device_data <- 
mutate(qb_device_data, decimal_hour = hours + (mins/60))

ggplot(qb_device_data) +
  aes(x = decimal_hour, y = counts) +
  geom_line() + 
  facet_grid(id ~ device)

Take the plots that you produced in part one and now polish them by:

Adding appropriate labels Changing the scales and coordinates when appropriate. Applying a unified theme, which is described below: Graphs should have white backgrounds, and use colour sparingly. There should be faint grid lines. Font sizes should be ~12pt although titles should be slightly larger and axis labels can be slightly smaller. All plots should use colours from the following company colour scheme.

col_scheme <- c("#E89FE9", "#50434F", "#B6A7B5", "#F9A472", "#BD7040")
theme_qb <- 
  theme(
    text = element_text(size = 12),
    title = element_text(size = 14),
    axis.text = element_text(size = 10),
    panel.background = element_rect(fill = "white"),
    panel.grid = element_line(colour = "grey90", linetype = "dashed")
  )
ggplot(qb_revenue_breakdown) +
  aes(x = Year, y = Revenue, fill = Product) +
  geom_col() +
  scale_fill_manual(values = col_scheme) +
  ggtitle(
    "Breakdown of QikBit Revenue by Product Line",
    subtitle =  "2018 and 2019"
  ) +
  theme_qb


kwikbit_sales <- subset(qb_monthly_sales, Cashflow == "Kwikbit Unit 1 Sales")

ggplot(kwikbit_sales) +
  aes(x = Date, y = Amount, group = Cashflow) +
  geom_line(size = 2, colour = col_scheme[3]) +
  theme_qb +
  scale_y_continuous("Sales", labels = scales::dollar_format(prefix = "£")) +
  ggtitle("Sales of Kwikbit Unit1", subtitle = "1 Aug 2018 to 1 July 2019")

revenue_and_costs <- subset(qb_monthly_sales, Cashflow != "Kwikbit Unit 1 Sales")

ggplot(revenue_and_costs) +
  aes(x = Date, y = Amount, colour = Cashflow, group = Cashflow) +
  geom_line(size = 2) +
  theme_qb +
  scale_colour_manual(values = col_scheme) +
  scale_y_continuous("Sales", labels = scales::dollar_format(prefix = "£")) +
  ggtitle("QikBit - Revenue and Costs", subtitle = "1 Aug 2018 to 1 July 2019")

ggplot(qb_competitors) +
  aes(x = Year, y = Revenue, fill = Company) +
  geom_area() +
  scale_y_continuous(labels = scales::dollar) +
  theme_qb +
  scale_fill_manual(values = col_scheme) +
  ggtitle(
    "Revenue in the Fitness Tracker Market by Company",
    subtitle = "2015 - 2019"
  )

ggplot(qb_competitors) +
  aes(x = Year, y = Revenue, colour = Company) +
  geom_line() +
  geom_point() +
  scale_y_continuous(labels = scales::dollar) +
  theme_qb +
  scale_colour_manual(values = col_scheme) +
  ggtitle(
    "Revenue in the Fitness Tracker Market by Company",
    subtitle = "2015 - 2019"
  )

ggplot(qb_device_data) +
  aes(x = decimal_hour, y = counts, colour = device) +
  geom_line() + 
  scale_x_continuous("Time (hours)") +
  scale_y_continuous("Steps") +
  facet_grid(id ~ device) +
  scale_colour_manual(values = col_scheme) +
  theme_qb +
  ggtitle("Comparison between KwikBit Unit1 and Competitors for 5 individuals")

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoQ29kZUNsYW5EYXRhKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3RoZW1lcykKbGlicmFyeSh2aXJpZGlzKQpgYGAKCkNPTVBBUklTT04KCkNyZWF0ZSBhIHN1aXRhYmxlIHBsb3QgZm9yIHRoZSBmb2xsb3dpbmcgdGhyZWUgZGF0YXNldHM6CgoKYGBge3J9CgpsYXRlX2RlbGl2ZXJpZXMKYGBgCgpMYXRlIERlbGl2ZXJpZXMKCmBgYHtyfQpnZ3Bsb3QobGF0ZV9kZWxpdmVyaWVzKSArCiBhZXMoeCA9IGRhdGUsIHkgPSBsYXRlX2RlbGl2ZXJpZXMsIGZpbGwgPSBsYXRlX2RlbGl2ZXJpZXMsIGJpbnMgPSAyMCkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKwogIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKHBhbGV0dGUgPSAiUGFzdGVsMiIpICsKICB0aGVtZV9idygpICsgCiAgbGFicygKICAgIHggPSAiRGF0ZSIsCiAgICB5ID0gImxhdGUgZGVsaXZlcmllcyIsCiAgICB0aXRsZSA9ICJMYXRlIERlbGl2ZXJpZXMiCiAgKSArICAKICB0aGVtZSh0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiaXRhbGljIiwgY29sb3VyID0gIkJsdWUiKSkKCmBgYAoKc29sdXRpb24gMgoKYGBge3J9CgpnZ3Bsb3QobGF0ZV9kZWxpdmVyaWVzKSArCiAgYWVzKHggPSBkYXRlLCB5ID0gbGF0ZV9kZWxpdmVyaWVzKSArCiAgZ2VvbV9saW5lKCkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBsYWJzKHggPSAieWVhciIsIHkgPSAibnVtYmVyIG9mIGxhdGUgZGVsaXZlcmllcyIpICsgCiAgdGhlbWVfbWluaW1hbCgpCgpgYGAKClJlY292ZXJ5IHRpbWUKCmBgYHtyfQoKcmVjb3ZlcnlfdGltZXMKYGBgCgoKYGBge3J9CmdncGxvdChyZWNvdmVyeV90aW1lcykgKwogIGFlcyh4ID0gcmVjb3ZlcnksIHkgPSBwcm9nbm9zaXMsIGZpbGwgPSB0cmVhdG1lbnRfZ3JvdXApICsgCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgc2NhbGVfZmlsbF9odWUoaCA9IGMoMTIwLDMwMCksIGMgPSA0MCwgbCA9IDQ1KSArCiAgdGhlbWVfY2xhc3NpYygxMSkgKwogIGxhYnMoCiAgICB4ID0gIlJlY292ZXJ5IiwKICAgIHkgPSAiUHJvZ25vc2lzIiwKICAgIHRpdGxlID0gIlJlY292ZXJ5IFRpbWVzIgogICkgKwogIHRoZW1lKAogICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LCBmYWNlID0gImJvbGQiLCBjb2xvdXIgPSAiYmx1ZSIpLAogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIlBpbmsiKSwgCiAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUsIGZhY2UgPSAiYm9sZCIsIGNvbG91ciA9ICJibHVlIikKICApCiAgCgpgYGAKCnNvbHV0aW9uIDIKCmBgYHtyfQpnZ3Bsb3QocmVjb3ZlcnlfdGltZXMpICsKICBhZXMoeCA9IHRyZWF0bWVudF9ncm91cCwgeSA9IHJlY292ZXJ5LCBmaWxsID0gcHJvZ25vc2lzKSArCiAgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArIAogIGxhYnMoeCA9ICJcbiBUcmVhdG1lbnQgR3JvdXAiLCB5ID0gIlJlY292ZXJ5IHRpbWUgKG1vbnRocykgXG4iKSArIAogICAgc2NhbGVfZmlsbF9jb2xvcmJsaW5kKCkKCgpgYGAKCiBGaXRuZXNzIExldmVsCiAKYGBge3J9CmZpdG5lc3NfbGV2ZWxzCmBgYAoKCmBgYHtyfQoKZ2dwbG90KGZpdG5lc3NfbGV2ZWxzKSArIAogIGFlcyh4ID0gYWdlLCB5ID0gZml0bmVzc19zY29yZSwgY29sb3VyID0gZ3JvdXApICsKICBnZW9tX2xpbmUoKSArCiAgdGhlbWVfbGlnaHQoKSArIAogIGZhY2V0X3dyYXAofiBncm91cCwgbmNvbCA9IDEwLCBzY2FsZXMgPSAiZnJlZSIpICsKICBzY2FsZV9jb2xvcl9ncmFkaWVudDJfdGFibGVhdSgpCgoKYGBgCgpTb2x1dGlvbiAyCgpgYGB7cn0KZ2dwbG90KGZpdG5lc3NfbGV2ZWxzKSArCiAgYWVzKHggPSBhZ2UsIHkgPSBmaXRuZXNzX3Njb3JlLCBncm91cCA9IGNoaWxkLCBjb2xvciA9IGNoaWxkKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgZmFjZXRfd3JhcCh+IGdyb3VwLCBuY29sID0gNSkgKyAKICBsYWJzKHkgPSAiZml0bmVzcyBzY29yZSBcbiIsIHggPSAiXG4gYWdlICh5ZWFycykiLCB0aXRsZSA9ICJJbmRpdmlkdWFsIGNoaWxkIGZpdG5lc3Mgc2NvcmUgYnkgR3JvdXAiKSArIAogIHNjYWxlX2NvbG91cl9odWUoZ3VpZGUgPSBndWlkZV9sZWdlbmQobnJvdyA9IDEwLCBieXJvdyA9IFRSVUUpKQoKYGBgCgoKCkNPTk5FQ1RJT04KCkJsb29kIFByZXNzdXJlCgpgYGB7cn0KZ2dwbG90KGJsb29kX3ByZXNzdXJlKSArCiAgYWVzKHggPSBzeXN0b2xpY19ibG9vZF9wcmVzc3VyZV9tbV9oZywgeSA9IGRhaWx5X3NhdHVyYXRlZF9mYXRfaW50YWtlX21nLCBjb2xvdXIgPSBkYWlseV9zYXR1cmF0ZWRfZmF0X2ludGFrZV9tZykgKwogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50Mihsb3cgPSAiYmx1ZSIsIGhpZ2ggPSAicmVkIiwgbWlkID0gIndoaXRlIiwgbWlkcG9pbnQgPSAxNSkgKwogIGxhYnMoCiAgICB4ID0gIlN5cyBCbG9vZCBQcmUiLAogICAgeSA9ICJEYWlseSBmYXQgaW50YWtlIChtZykiLAogICAgdGl0bGUgPSAiQmxvb2QgUHJlc3N1ZSIsCiAgICBzdWJ0aXRsZSA9ICJmYXQgSW50YWtlIChtZykiCiAgKSArIAogIHRoZW1lX2xpZ2h0KCkKYGBgCgpTb2x1dGlvbiAyCgpgYGB7cn0KZ2dwbG90KGJsb29kX3ByZXNzdXJlKSArCiAgYWVzKAogICAgeCA9IGRhaWx5X3NhdHVyYXRlZF9mYXRfaW50YWtlX21nLAogICAgeSA9IHN5c3RvbGljX2Jsb29kX3ByZXNzdXJlX21tX2hnCiAgKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgbGFicyh4ID0gImRhaWx5IGZhdCBpbnRha2UgKG1nKSIsIHkgPSAic3lzdG9saWMgYmxvb2QgcHJlc3N1cmUgKG1tSGcpIikKYGBgCgpDYXIgdXNlCgpgYGB7cn0KY2FyX3VzZQpgYGAKCgoKYGBge3J9CmdncGxvdChjYXJfdXNlKSArCiAgYWVzKHggPSBjaXR5LCB5ID0gcG9wdWxhdGlvbiwgY29sb3VyID0gY2FyX3VzZV9wZXJjZW50KSArCiAgZ2VvbV9wb2ludCgpICsKICBzY2FsZV9jb2xvcl9kaXN0aWxsZXIocGFsZXR0ZSA9ICJQdU9yIikgKwogIHRoZW1lX2RhcmsoKSArCiAgbGFicygKICAgIHRpdGxlID0gIkNhciBVc2UiLCAKICAgIHN1YnRpdGxlID0gIkNhciB1c2UiCiAgKQogIAogIAoKYGBgCgpzb2x1dGlvbiAyCgpgYGB7cn0KZ2dwbG90KGNhcl91c2UpICsKICBhZXMoCiAgICB4ID0gY2FyX3VzZV9wZXJjZW50LAogICAgeSA9IGFpcl9zbzJfY29uY2VudHJhdGlvbl9wcG0sCiAgICBzaXplID0gcG9wdWxhdGlvbgogICkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsgCiAgbGFicyh4ID0gImNhciB1c2UgKCUpIiwgeSA9ICJhaXIgQ08yIGNvbmNlbnRyYXRpb24gKHBwbSkiKQoKYGBgCgoKRElTVFJJQlVUSU9OCgpEMjAgT3V0Y29tZQoKYGBge3J9CmdncGxvdChkMjBfb3V0Y29tZXMpICsKICBhZXMoeCA9IG91dGNvbWUpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMjAsIGNvbCA9ICJ3aGl0ZSIpIAoKYGBgCnNvbHV0aW9uIDIKCmBgYHtyfQpnZ3Bsb3QoZDIwX291dGNvbWVzKSArCiAgYWVzKHggPSBvdXRjb21lKSArCiAgZ2VvbV9kZW5zaXR5KCkKCmBgYAoKCgpDT01QT1NJVElPTgoKUGVuc2lvbiBTdXJwbHVzCgpgYGB7cn0KZ2dwbG90KHBlbnNpb25fc3VycGx1cykgKwogIGFlcyh4ID0gaXRlbSwgeSA9IGJhbGFuY2UsIGZpbGwgPSBiYWxhbmNlID4gMCkgKwogIGdlb21fY29sKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIGhqdXN0ID0gMSkpICsgCiAgY29vcmRfZmxpcCgpIAoKYGBgCgoKUGVuc2lvbiBMaWFiaWxpdGllcwoKYGBge3J9CmdncGxvdChwZW5zaW9uX2xpYWJpbGl0aWVzKSArCiAgYWVzKHggPSB5ZWFyLCB5ID0gbGlhYmlsaXR5X21pbGxpb25zLCBmaWxsID0gbGlhYmlsaXR5X3R5cGUpICsKICBnZW9tX2NvbCgpICsgCiAgc2NhbGVfZmlsbF9jb2xvcmJsaW5kKCkKCmBgYAoKCkhvbWV3b3JrIHBhcnQgMQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShDb2RlQ2xhbkRhdGEpCmxpYnJhcnkoZHBseXIpCgpgYGAKCgoxLiBUYWtlIHRoZSBkYXRhIGluIHRoZSBkYXRhc2V0IHFiX3JldmVudWVfYnJlYWtkb3duIGFuZCBtYWtlIGEgc3RhY2tlZCBiYXIgY2hhcnQgc2hvd2luZyB0aGUgc291cmNlcyBvZiByZXZlbnVlIGFjcm9zcyB0aGUgdHdvIHllYXJzIGluIHRoZSBkYXRhc2V0LgoKYGBge3J9CmdncGxvdChxYl9yZXZlbnVlX2JyZWFrZG93bikgKwogIGFlcyh4ID0gWWVhciwgeSA9IFJldmVudWUsIGZpbGwgPSBQcm9kdWN0KSArCiAgZ2VvbV9jb2woKQoKYGBgCgoyLiBNYWtlIGEgbGluZSBjaGFydCBzaG93aW5nIG1vbnRobHkgc2FsZXMgb2YgdGhlIOKAnGZsYWdzaGlwIHByb2R1Y3TigJ0gLSB0aGUgS3dpa0JpdCBVbml0MSAtIG92ZXIgdGhlIGxhc3QgeWVhci4gVGhpcyBkYXRhIGlzIGluc2lkZSBxYl9tb250aGx5X3NhbGVzLCBidXQgeW91IHdpbGwgbmVlZCB0byB1c2Ugc3Vic2V0LgoKYGBge3J9Cgprd2lrYml0X3NhbGVzIDwtIHN1YnNldChxYl9tb250aGx5X3NhbGVzLCBDYXNoZmxvdyA9PSAiS3dpa2JpdCBVbml0IDEgU2FsZXMiKQoKZ2dwbG90KGt3aWtiaXRfc2FsZXMpICsKICBhZXMoeCA9IERhdGUsIHkgPSBBbW91bnQpICsKICBnZW9tX2xpbmUoKSAKYGBgCgozLiBNYWtlIGEgbGluZSBjaGFydCBzaG93aW5nIG1vbnRobHkgcmV2ZW51ZSBhbmQgY29zdHMgb3ZlciB0aGUgbGFzdCB5ZWFyLiBUaGlzIGRhdGEgaXMgYWxzbyBpbiBxYl9tb250aGx5X3NhbGVzLgoKYGBge3J9CnJldmVudWVfYW5kX2Nvc3RzIDwtIHN1YnNldChxYl9tb250aGx5X3NhbGVzLCBDYXNoZmxvdyAhPSAiS3dpa2JpdCBVbml0IDEgU2FsZXMiKQoKZ2dwbG90KHJldmVudWVfYW5kX2Nvc3RzKSArCiAgYWVzKHggPSBEYXRlLCB5ID0gQW1vdW50LCBjb2xvdXIgPSBDYXNoZmxvdykgKwogIGdlb21fbGluZSgpCgpgYGAKCgo0LiBTaG93IGFubnVhbCBzYWxlcyBvZiBwZXJzb25hbCBmaXRuZXNzIHRyYWNrZXJzIG92ZXIgdGhlIGxhc3QgNSB5ZWFycyBicm9rZW4gZG93biBieSBjb21wYW55IGFzIGEgcmliYm9uIHBsb3QgKHVzZSBnZW9tX2FyZWEpLiBUaGlzIGRhdGEgaXMgaW4gcWJfY29tcGV0aXRvcnMuCgpgYGB7cn0KZ2dwbG90KHFiX2NvbXBldGl0b3JzKSArCiAgYWVzKHggPSBZZWFyLCB5ID0gUmV2ZW51ZSwgZmlsbCA9IENvbXBhbnkpICsKICBnZW9tX2FyZWEoKSAKCmBgYAoKCgo1LiBOb3cgc2hvdyB0aGUgc2FsZXMgZnJvbSB0aGUgNSBjb21wZXRpdG9ycyBhcyBhIGxpbmUgZ3JhcGguIEluY2x1ZGUgYW4gZXh0cmEgbGF5ZXIgdGhhdCBzaG93cyB0aGUgZGF0YSBwb2ludHMgdXNlZCB0byBtYWtlIHRoZSBsaW5lcy4KCmBgYHtyfQpnZ3Bsb3QocWJfY29tcGV0aXRvcnMpICsKICBhZXMoeCA9IFllYXIsIHkgPSBSZXZlbnVlLCBjb2xvdXIgPSBDb21wYW55KSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKQoKYGBgCgo2LiBOb3cgdGhlIGNvbXBhbnkgd2FudHMgdG8gY29tcGFyZSB0aGUgbnVtYmVyIG9mIHN0ZXBzIHRoYXQgdGhlaXIgZGV2aWNlIGNvdW50cyB2cy4gdGhlaXIgY29tcGV0aXRvcnMuIE1ha2UgYSBsaW5lIGdyYXBoIG9mIHRoZSBudW1iZXIgb2Ygc3RlcHMgdGhyb3VnaG91dCB0aW1lLCBhbmQgdXNlIGZhY2V0aW5nIHRvIGNvbXBhcmUgYmV0d2VlbiBpbmRpdmlkdWFscyBhbmQgcGVvcGxlLiBEYXRhIGlzIGluIHFiX2RldmljZV9kYXRhLgoKYGBge3J9CnFiX2RldmljZV9kYXRhIDwtIAptdXRhdGUocWJfZGV2aWNlX2RhdGEsIGRlY2ltYWxfaG91ciA9IGhvdXJzICsgKG1pbnMvNjApKQoKZ2dwbG90KHFiX2RldmljZV9kYXRhKSArCiAgYWVzKHggPSBkZWNpbWFsX2hvdXIsIHkgPSBjb3VudHMpICsKICBnZW9tX2xpbmUoKSArIAogIGZhY2V0X2dyaWQoaWQgfiBkZXZpY2UpCgpgYGAKCgpUYWtlIHRoZSBwbG90cyB0aGF0IHlvdSBwcm9kdWNlZCBpbiBwYXJ0IG9uZSBhbmQgbm93IHBvbGlzaCB0aGVtIGJ5OgoKQWRkaW5nIGFwcHJvcHJpYXRlIGxhYmVscwpDaGFuZ2luZyB0aGUgc2NhbGVzIGFuZCBjb29yZGluYXRlcyB3aGVuIGFwcHJvcHJpYXRlLgpBcHBseWluZyBhIHVuaWZpZWQgdGhlbWUsIHdoaWNoIGlzIGRlc2NyaWJlZCBiZWxvdzoKR3JhcGhzIHNob3VsZCBoYXZlIHdoaXRlIGJhY2tncm91bmRzLCBhbmQgdXNlIGNvbG91ciBzcGFyaW5nbHkuClRoZXJlIHNob3VsZCBiZSBmYWludCBncmlkIGxpbmVzLgpGb250IHNpemVzIHNob3VsZCBiZSB+MTJwdCBhbHRob3VnaCB0aXRsZXMgc2hvdWxkIGJlIHNsaWdodGx5IGxhcmdlciBhbmQgYXhpcyBsYWJlbHMgY2FuIGJlIHNsaWdodGx5IHNtYWxsZXIuCkFsbCBwbG90cyBzaG91bGQgdXNlIGNvbG91cnMgZnJvbSB0aGUgZm9sbG93aW5nIGNvbXBhbnkgY29sb3VyIHNjaGVtZS4KCgpgYGB7cn0KY29sX3NjaGVtZSA8LSBjKCIjRTg5RkU5IiwgIiM1MDQzNEYiLCAiI0I2QTdCNSIsICIjRjlBNDcyIiwgIiNCRDcwNDAiKQp0aGVtZV9xYiA8LSAKICB0aGVtZSgKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLAogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleTkwIiwgbGluZXR5cGUgPSAiZGFzaGVkIikKICApCmdncGxvdChxYl9yZXZlbnVlX2JyZWFrZG93bikgKwogIGFlcyh4ID0gWWVhciwgeSA9IFJldmVudWUsIGZpbGwgPSBQcm9kdWN0KSArCiAgZ2VvbV9jb2woKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sX3NjaGVtZSkgKwogIGdndGl0bGUoCiAgICAiQnJlYWtkb3duIG9mIFFpa0JpdCBSZXZlbnVlIGJ5IFByb2R1Y3QgTGluZSIsCiAgICBzdWJ0aXRsZSA9ICAiMjAxOCBhbmQgMjAxOSIKICApICsKICB0aGVtZV9xYgpgYGAKCmBgYHtyfQoKa3dpa2JpdF9zYWxlcyA8LSBzdWJzZXQocWJfbW9udGhseV9zYWxlcywgQ2FzaGZsb3cgPT0gIkt3aWtiaXQgVW5pdCAxIFNhbGVzIikKCmdncGxvdChrd2lrYml0X3NhbGVzKSArCiAgYWVzKHggPSBEYXRlLCB5ID0gQW1vdW50LCBncm91cCA9IENhc2hmbG93KSArCiAgZ2VvbV9saW5lKHNpemUgPSAyLCBjb2xvdXIgPSBjb2xfc2NoZW1lWzNdKSArCiAgdGhlbWVfcWIgKwogIHNjYWxlX3lfY29udGludW91cygiU2FsZXMiLCBsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcl9mb3JtYXQocHJlZml4ID0gIsKjIikpICsKICBnZ3RpdGxlKCJTYWxlcyBvZiBLd2lrYml0IFVuaXQxIiwgc3VidGl0bGUgPSAiMSBBdWcgMjAxOCB0byAxIEp1bHkgMjAxOSIpCgpgYGAKCgpgYGB7cn0KcmV2ZW51ZV9hbmRfY29zdHMgPC0gc3Vic2V0KHFiX21vbnRobHlfc2FsZXMsIENhc2hmbG93ICE9ICJLd2lrYml0IFVuaXQgMSBTYWxlcyIpCgpnZ3Bsb3QocmV2ZW51ZV9hbmRfY29zdHMpICsKICBhZXMoeCA9IERhdGUsIHkgPSBBbW91bnQsIGNvbG91ciA9IENhc2hmbG93LCBncm91cCA9IENhc2hmbG93KSArCiAgZ2VvbV9saW5lKHNpemUgPSAyKSArCiAgdGhlbWVfcWIgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gY29sX3NjaGVtZSkgKwogIHNjYWxlX3lfY29udGludW91cygiU2FsZXMiLCBsYWJlbHMgPSBzY2FsZXM6OmRvbGxhcl9mb3JtYXQocHJlZml4ID0gIsKjIikpICsKICBnZ3RpdGxlKCJRaWtCaXQgLSBSZXZlbnVlIGFuZCBDb3N0cyIsIHN1YnRpdGxlID0gIjEgQXVnIDIwMTggdG8gMSBKdWx5IDIwMTkiKQoKYGBgCgoKCmBgYHtyfQpnZ3Bsb3QocWJfY29tcGV0aXRvcnMpICsKICBhZXMoeCA9IFllYXIsIHkgPSBSZXZlbnVlLCBmaWxsID0gQ29tcGFueSkgKwogIGdlb21fYXJlYSgpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpkb2xsYXIpICsKICB0aGVtZV9xYiArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sX3NjaGVtZSkgKwogIGdndGl0bGUoCiAgICAiUmV2ZW51ZSBpbiB0aGUgRml0bmVzcyBUcmFja2VyIE1hcmtldCBieSBDb21wYW55IiwKICAgIHN1YnRpdGxlID0gIjIwMTUgLSAyMDE5IgogICkKCmBgYAoKCmBgYHtyfQpnZ3Bsb3QocWJfY29tcGV0aXRvcnMpICsKICBhZXMoeCA9IFllYXIsIHkgPSBSZXZlbnVlLCBjb2xvdXIgPSBDb21wYW55KSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21fcG9pbnQoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6ZG9sbGFyKSArCiAgdGhlbWVfcWIgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gY29sX3NjaGVtZSkgKwogIGdndGl0bGUoCiAgICAiUmV2ZW51ZSBpbiB0aGUgRml0bmVzcyBUcmFja2VyIE1hcmtldCBieSBDb21wYW55IiwKICAgIHN1YnRpdGxlID0gIjIwMTUgLSAyMDE5IgogICkKCmBgYAoKCmBgYHtyfQpnZ3Bsb3QocWJfZGV2aWNlX2RhdGEpICsKICBhZXMoeCA9IGRlY2ltYWxfaG91ciwgeSA9IGNvdW50cywgY29sb3VyID0gZGV2aWNlKSArCiAgZ2VvbV9saW5lKCkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoIlRpbWUgKGhvdXJzKSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIlN0ZXBzIikgKwogIGZhY2V0X2dyaWQoaWQgfiBkZXZpY2UpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGNvbF9zY2hlbWUpICsKICB0aGVtZV9xYiArCiAgZ2d0aXRsZSgiQ29tcGFyaXNvbiBiZXR3ZWVuIEt3aWtCaXQgVW5pdDEgYW5kIENvbXBldGl0b3JzIGZvciA1IGluZGl2aWR1YWxzIikKCmBgYAoK